home *** CD-ROM | disk | FTP | other *** search
File List | 1994-09-02 | 16.6 KB | 406 lines |
- ;***************************************************************
- ;
- ; Stereo chorus for the DSP56001 signal processor.
- ; Developed by Quinn Jensen (jensenq@qcj.icon.com).
- ;
- ; This program fragment implements a stereo "chorus" effect
- ; on a DSP56001 processor. Chorus adds depth and warmth to
- ; sound by creating the illusion that more instruments
- ; are involved in the sound than really are. It does this by
- ; mixing together a delayed version of the input with the input
- ; itself. This program uses the following signal flow.
- ;
- ;
- ; Left in ------+------- "dry" gain -----------> sum -----> Left out
- ; | ^
- ; v |
- ; sum --> delay ---> "wet" gain -----+
- ; ^ |
- ; | v -
- ; Right in -----+------- "dry" gain -----------> sum -----> Right out
- ;
- ;
- ; Note that the delay line output is negated before summing with the
- ; right input signal. This throws in 180 degrees of phase shift
- ; making for interesting results even with mono inputs
- ; (i.e. Left in == Right in).
- ;
- ; Chorus uses a delay time of between about 10 and 50ms in some commercial
- ; units. This program can be configured for longer delays.
- ; In the chorus effect, the delay time is slowly varied, adding a very
- ; subtle pitch shift. The depth and speed of the delay-time modulation
- ; are adjustable to taste. The greater the depth or speed, the greater
- ; the coloration of the signal.
- ;
- ; Variations in this algorithm are possible and encouraged. I came
- ; up with this code after studying the impulse response and characteristics
- ; of a commercial stereo chorus pedal and reading various articles in magazines
- ; and on usenet over the years. My somewhat dry TX81 synthesizer sounds pretty
- ; good with this and other effects I run on the 56001.
- ;
- ; A recent article with a pretty good not-too-technical overview of chorus
- ; and other effects: Gary Hall, "From the Top: Effects, the Essential Musical
- ; Spice," _Electronic Musician_, August 1991, pp. 62-68.
- ;
- ; I would enjoy seeing any improvements to the code.
- ;
- include "tdsg.a56" ;hardware specific initialization code
-
- ;***************************************************************
- ;
- ; Data and constants
- ;
- ;***************************************************************
-
- P:0076 dot ;remember where we were in P-space
- X:0020 org x:$20 ;put runtime variables in on-chip X-space
-
- ; A spreadsheet was used to calculate the following numbers
-
- ; Sample rate 32.5500 kc
- ;
- ; Delay time (4-52) 28.0000 ms delay time knob
- ; Depth (1-10) 10.0000 depth knob (I like it deep)
- ; Speed (1-10) 0.0000 speed knob (I like it slow)
- ;
- ; max depth +/- 24.0000 ms
- ; min delay 4.0000 ms
- ; max delay 52.0000 ms
- ; 1/2 cycle period 5.0000 s
- ; samples per 1/2 cyc 162750.0000
- ; time delta/samp 0.2949 us
- ; offset samp/samp 0.0096
- ;
- FFFF7E doff_i equ -130 ;initial delay offset (tap)
- 0.0096 ddeltaf equ 0.0096 ;delta-delay, per sample
- 027BBE dspeed_i equ 162750 ;number of samples per
- ;half cycle of triangle wave
- ;delay-time modulator
- ;
- ; Delay time (ms) tap tap delay
- ;
- ; 1 32.5500 1 0.03
- ; 2 65.1000 2 0.06
- ; 4 130.2000 4 0.12
- ; 5 162.7500 8 0.25
- ; 8 260.4000 16 0.49
- ; 10 325.5000 32 0.98
- ; 20 651.0000 64 1.97
- ; 25 813.7500 128 3.93
- ; 40 1302.0000 256 7.86
- ; 50 1627.5000 512 15.73
- ; 60 1953.0000 1024 31.46
- ; 70 2278.5000 2048 62.92
- ; 80 2604.0000 4096 125.84
- ; 90 2929.5000 8192 251.67
- ; 100 3255.0000 16384 503.35
-
- ;
- ; The delay line is in off-chip X memory
- ;
- 002000 delay equ $2000
- 001000 dmax equ 4096 ;125 ms (probably way too long)
- ;
- ; doff and ddelta are 48-bit quantities
- ;
- X:0020 FFFF7E doff dc doff_i ;current delay distance
- Y:0020 org y:doff
- Y:0020 000000 dc 0
-
- X:0021 org x:doff+1
- X:0021 000000 ddelta dc 0 ;delta delay per sample
- Y:0021 org y:ddelta
- Y:0021 013A93 dc ddeltaf
-
- X:0022 org x:ddelta+1
-
- X:0022 027BBE dspeed dc dspeed_i ;samples per half cycle of triangle modulator
- X:0023 000000 dtoggle dc 0 ;current sample count
- X:0024 delayout
- X:0024 000000 dc 0 ;current delay-line output
-
- Y:0000 org y:$0
-
- P:0076 org p:dot ;go back to P-space
- ;***************************************************************
- ;
- ; Initialization code
- ;
- ;***************************************************************
- P:0076 hf_init
- P:0076 61F400 move #delay,r1 ;delay line input
- P:0077 002000
- P:0078 05F421 movec #dmax-1,m1 ;
- P:0079 000FFF
- P:007A 71F400 move #doff_i,n1 ;distance to output
- P:007B FFFF7E
- P:007C 00000C rts
- ;
- ;***************************************************************
- ;
- ; Sample-rate computations. Call chorus_compute at
- ; interrupt time when both left and right inputs are
- ; ready.
- ;
- ; fs = 32.552083 kHz
- ;
- ; x:<in_l left-channel input
- ; x:<in_r right-channel input
- ; x:<out_l left-channel output
- ; x:<out_r right-channel output
- ;
- ;***************************************************************
-
- P:007D hf_comp
- P:007D 0D0066 jsr <saveregs
- ;
- ; output and input mix
- ;
- P:007E 253813 clr a #.4375,x1 ;clr a, get input scale
- P:007F 27401B clr b #.5,y1 ;clr b, get output scaler
-
- P:0080 46A400 move x:<delayout,y0 ;get delay out
-
- P:0081 4480BB macr y0,y1,b x:<in_l,x0 ;b = .5 * delay, x0=in_l
- P:0082 21E6CB macr x0,y1,b b,y0 ;b += .5 * in_l, y0=b
- P:0083 5704A3 macr x0,x1,a b,x:<out_l ;a = x1 * in_l, L = b
- P:0084 20CF00 move y0,b ;b = -y0
- P:0085 44813E neg b x:<in_r,x0 ;x0 = in_r
- P:0086 2000CB macr x0,y1,b ;b += .5 * in_r
- P:0087 5705A3 macr x0,x1,a b,x:<out_r ;R = b, a += x1 * in_r
- ;
- ; delay line in
- ;
- P:0088 565900 move a,x:(r1)+
- ;
- ; delay line length modulation. A simple triangle-wave modulator
- ; is used. A sine-wave modulator would be much better, especially
- ; with deeper and/or faster settings.
- ;
- P:0089 48A000 move l:<doff,a ;a = current offset
- P:008A 42A100 move l:<ddelta,x ;x = current delta
- P:008B 200020 add x,a
- P:008C 482000 move a,l:<doff ;new offset = a + x
- P:008D 219900 move a1,n1
-
- P:008E 20AF00 move x1,b ;save delta for later use
- ;
- ; smoothly transition between delay-line offsets by
- ; interpolating the current sample with the previous or next
- ; one depending on whether the delay is currently getting longer or
- ; shorter. Otherwise, an obnoxious click results when the offset snaps
- ; to the next integral value. This does have a low-pass effect on the
- ; delayed signal path but it is not objectionable.
- ;
- P:008F 5EA000 move y:<doff,a ;compute |frac(doff)|
- P:0090 44F423 lsr a #$800000,x0
- P:0091 800000
- P:0092 254042 or x0,a #.5,x1
- P:0093 218400 move a1,x0
- P:0094 2000A4 mpy -x0,x1,a
- P:0095 21C60B tst b a,y0 ;y0 = 0.5 * |frac(doff)|
- P:0096 0AF0A3 jpl shorter ;on positive delta, the
- P:0097 0000A1
- ;delay is shortening
-
- P:0098 205100 move (r1)- ;get previous sample
- P:0099 44E900 move x:(r1+n1),x0
- P:009A 2F40D0 mpy y0,x0,a #.5,b ;scale
- P:009B 20595C sub y0,b (r1)+ ;compute scale for cur sample
- P:009C 21E600 move b,y0
- P:009D 44E900 move x:(r1+n1),x0 ;get cur sample
- P:009E 2000D2 mac x0,y0,a ;scale and sum
- P:009F 0AF080 jmp endpan
- P:00A0 0000A7
-
- P:00A1 shorter
- P:00A1 44E900 move x:(r1+n1),x0 ;get cur sample
- P:00A2 2F40D0 mpy y0,x0,a #.5,b ;scale
- P:00A3 20595C sub y0,b (r1)+ ;compute scale for next sample
- P:00A4 21E600 move b,y0
- P:00A5 44E900 move x:(r1+n1),x0 ;get next sample
- P:00A6 2051D2 mac x0,y0,a (r1)- ;scale and sum
- P:00A7 endpan
- P:00A7 562400 move a,x:<delayout ;store resulting output
- ;
- ; update the triangle wave modulation (sinewave would be better)
- ;
- P:00A8 56A300 move x:<dtoggle,a ;decrement toggle count
- P:00A9 44F400 move #>1,x0
- P:00AA 000001
- P:00AB 200044 sub x0,a
- P:00AC 562300 move a,x:<dtoggle
- P:00AD 0AF0A7 jgt notogg ;time to toggle?
- P:00AE 0000B3
- P:00AF 44A200 move x:<dspeed,x0 ;yes, negate delta and reset
- P:00B0 48A100 move l:<ddelta,a
- P:00B1 442336 neg a x0,x:<dtoggle
- P:00B2 482100 move a,l:<ddelta
- P:00B3 notogg
- P:00B3 bypass
- P:00B3 0D006F jsr <restregs
- P:00B4 00000C rts
-
- end
-
- Summary of psect usage
-
- section seg base last top used avail total
- -------------------------------------------------------------------------
-
-
- Symbol Table
- -------------------------------------
- ddelta 000021
- ddeltaf 0.0096000000
- ssi_int 000061
- ssix 000010
- notogg 0000B3
- delayout 000024
- delay 002000
- init_stereo 000059
- start 000040
- in_rs 000003
- in_ls 000002
- in_r 000001
- in_l 000000
- dmax 001000
- endpan 0000A7
- doff 000020
- doff_i FFFF7E
- dot 000076
- mainloop 000060
- hf_comp 00007D
- hf_init 000076
- dtoggle 000023
- saveregs 000066
- savey 00000B
- savex 00000A
- saveb2 000009
- saveb10 000008
- savea2 000007
- savea10 000006
- dspeed 000022
- dspeed_i 027BBE
- restregs 00006F
- out_r 000005
- out_l 000004
- bypass 0000B3
- shorter 0000A1
- m_scl1 00000F
- m_scl0 00000E
- m_scl 00C000
- m_ssl1 00000D
- m_ssl0 00000C
- m_ssl 003000
- m_hpl1 00000B
- m_hpl0 00000A
- m_hpl 000C00
- m_ibl2 000005
- m_ibl1 000004
- m_ibl0 000003
- m_ibl 000038
- m_ial2 000002
- m_ial1 000001
- m_ial0 000000
- m_ial 000007
- m_ipr 00FFFF
- m_rdf 000007
- m_tde 000006
- m_roe 000005
- m_tue 000004
- m_rfs 000003
- m_tfs 000002
- m_if1 000001
- m_if0 000000
- m_if 000002
- m_srie 00000F
- m_stie 00000E
- m_sre 00000D
- m_ste 00000C
- m_mod 00000B
- m_gck 00000A
- m_syn 000009
- m_fsl 000008
- m_sckd 000005
- m_scd2 000004
- m_scd1 000003
- m_scd0 000002
- m_scd 00001C
- m_of1 000001
- m_of0 000000
- m_of 000003
- m_psr 00000F
- m_wl1 00000E
- m_wl0 00000D
- m_wl 006000
- m_dc 001F00
- m_pm 0000FF
- m_tsr 00FFEE
- m_sr 00FFEE
- m_crb 00FFED
- m_cra 00FFEC
- m_tx 00FFEF
- m_rx 00FFEF
- m_tcm 00000F
- m_rcm 00000E
- m_scp 00000D
- m_cod 00000C
- m_cd 000FFF
- m_r8 000007
- m_fe 000006
- m_pe 000005
- m_or 000004
- m_idle 000003
- m_rdrf 000002
- m_tdre 000001
- m_trne 000000
- m_tmie 00000D
- m_tie 00000C
- m_rie 00000B
- m_ilie 00000A
- m_te 000009
- m_re 000008
- m_woms 000007
- m_rwi 000006
- m_wake 000005
- m_sbk 000004
- m_wds2 000002
- m_wds1 000001
- m_wds0 000000
- m_wds 000003
- m_sccr 00FFF2
- m_ssr 00FFF1
- m_scr 00FFF0
- m_stxa 00FFF3
- m_stxh 00FFF6
- m_stxm 00FFF5
- m_stxl 00FFF4
- m_srxh 00FFF6
- m_srxm 00FFF5
- m_srxl 00FFF4
- m_dma 000007
- m_hf1 000004
- m_hf0 000003
- m_hf 000018
- m_hcp 000002
- m_htde 000001
- m_hrdf 000000
- m_hf3 000004
- m_hf2 000003
- m_hcie 000002
- m_htie 000001
- m_hrie 000000
- m_htx 00FFEB
- m_hrx 00FFEB
- m_hsr 00FFE9
- m_hcr 00FFE8
- m_pcd 00FFE5
- m_pcddr 00FFE3
- m_pcc 00FFE1
- m_pbd 00FFE4
- m_pbddr 00FFE2
- m_pbc 00FFE0
- m_bcr 00FFFE
- errors=0
-